using System;
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Framework.Base;

namespace Framework.MVC.Model
{
    /// <summary>
    ///  数据基类
    /// </summary>
    public class ModelBase : Event.Event, IPoolObj
    {       
        private static string PROP_KEY = "_PROP_";
        
        private readonly Dictionary<string, object> m_propDict = new Dictionary<string, object>();

        public ModelBase() {}

        public ModelBase(Dictionary<string, object> initProp)
        {
            foreach (var pair in initProp)
            {
                this.m_propDict[pair.Key] = pair.Value;
            }    
        }

        /// <summary>
        ///  监听 一个属性的改变
        /// </summary>
        /// <param name="propName"> 属性名字</param>
        /// <param name="func"> 回调</param>
        public void ListenPropChg<T>(string propName, Event.FuncDelegate<T> func)
        {
            if (m_propDict.ContainsKey(propName))
            {
                AddListener<T>(PROP_KEY + propName, func);
            }
        }
        /// <summary>
        ///  监听属性变化并且回调
        /// </summary>
        /// <param name="propName">属性名字</param>
        /// <param name="func">回调</param>
        public void ListenPropChgAndCal<T>(string propName, Event.FuncDelegate<T> func) where  T:class
        {
            if (m_propDict.ContainsKey(propName))
            {
                AddListener<T>(PROP_KEY + propName, func);
                func.Invoke(m_propDict[propName] as T);
            }
        }
        
        /// <summary>
        ///  移除一个属性的监听
        /// </summary>
        /// <param name="propName">属性名字</param>
        /// <param name="func">回调</param>
        public void RemovePropListen<T>(string propName, Event.FuncDelegate<T> func)
        {
            if (m_propDict.ContainsKey(propName))
            {
                RemoveListener<T>(PROP_KEY + propName, func);
            }
        }

        /// <summary>
        ///  设置一个属性
        /// </summary>
        /// <param name="propName"> 属性名字</param>
        /// <param name="propValue">属性值</param>
        /// <param name="isEmitEvent">是否发送事件</param>
        public void SetProp<T>(string propName,  T propValue, bool isEmitEvent = true)
        {
            if (!m_propDict[propName].Equals(propValue))
            {
                m_propDict[propName] = propValue;
                if (isEmitEvent)
                {
                    Emit<T>(PROP_KEY + propName,propValue);
                }
            }
        }
        
        /// <summary>
        ///  批量更新属性
        /// </summary>
        /// <param name="updateProp"> 属性字典</param>
        /// <param name="isEmitEvent"> 是否发送事件</param>
        public void UpdateProp<T>(Dictionary<string, T> updateProp, bool isEmitEvent = true)
        {
            if (isEmitEvent)
            {
                List<string> diffPropList = new List<string>();
                foreach (var pair in updateProp)
                {
                    if (m_propDict[pair.Key] != (pair.Value as object))
                    {
                        m_propDict[pair.Key] = pair.Value;
                        diffPropList.Add(pair.Key);
                    }
                }

                foreach (var propName in diffPropList)
                {
                    Emit<T>(PROP_KEY + propName, (T)m_propDict[propName]);
                }
            }
            else
            {
                foreach (var pair in updateProp)
                {
                    m_propDict[pair.Key] = pair.Value;
                }
            }
        }
        
        /// <summary>
        ///  获得一个属性
        /// </summary>
        /// <param name="propName">属性名字</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public object GetProp(string propName, object defaultValue = null)
        {
            var outValue = defaultValue;
            if (this.m_propDict.TryGetValue(propName, out outValue))
            {
                return outValue;
            }
            return defaultValue;
        }


        public T GetProp<T>(string propName, T defaultValue = default(T))
        {
            object outValue = defaultValue;
            if (this.m_propDict.TryGetValue(propName, out outValue))
            {
                return (T)outValue;

            }
            else
            {
                return defaultValue;
            }
        }


        public void OnFetch()
        {
        }

        // 加入回收池
        public  void OnRecycle()
        {
            this.m_propDict.Clear();
            Clear();
        }

    }
}